package com.onpositive.utils;

import java.util.ArrayList;

public class MarkedTree {
	
	public static final int rootVertexParentIndex = Integer.MIN_VALUE;
	
	public class MarkedVertex{
		
		
		int index ;
		int parent = rootVertexParentIndex ;
		private Object mark ;
		ArrayList<Integer> children ;
		
		public MarkedVertex(){}
		
		public MarkedVertex( String mark )
		{
			this.mark = mark ;
		}	
		
		public int getParent() {
			return parent;
		}
		public void setParent(int parent) {
			this.parent = parent;
		}
		public Object getMark() {
			return mark;
		}
		public void setMark( Object mark) {
			this.mark = mark;
		}
		public ArrayList<Integer> getChildren() {
			return children;
		}
		
		public void addChild( MarkedVertex v )
		{
			if( children.contains( v.getIndex() ) )
				return ;
			
			children.add( v.getIndex() ) ;
			v.setParent( this.getIndex() ) ;
			v.setIndex( MarkedTree.this.vertices.size() ) ;
			MarkedTree.this.vertices.add(v);
		}
		public void addChild( int i )
		{
			if( children.contains(i) )
				return ;
			
			MarkedVertex chVert = MarkedTree.this.getVertex(i) ;
			if( chVert == null )
				throw new IllegalStateException("Invalid child vertex index") ;

			chVert.setParent( this.index ) ;
			children.add(i) ;			
		}
		
		public int getIndex() {
			return index;
		}
		public void setIndex(int index) {
			this.index = index;
		}
		
		
	}
	public MarkedTree(){}
	
	public MarkedTree( int[] inputArray ){
		takeSpecificationArray(inputArray) ;
	}
	
	public int getSize()
	{
		return vertices != null ? vertices.size() : -1 ;
	}	

	ArrayList<MarkedVertex> vertices = new ArrayList<MarkedTree.MarkedVertex>() ;
	public MarkedVertex getRoot() 
	{
		if ( vertices.size() == 0 )
			vertices.add( new MarkedVertex() ) ;
		
		return vertices.get(0) ;		
	}
	
	public MarkedVertex getVertex( int i )
	{
		return i >= 0 && i < vertices.size() ? vertices.get(i) : null ;
	}
	
	public int[] getSpecificationArray()
	{		
		ArrayList<Integer> list = new ArrayList<Integer>() ;
		
		int size = vertices.size();
		list.add( size ) ;
		
		int vericesOffsetsStart = list.size() ;
		
		//some empty space for offsets
		for( int i = 0 ; i < size + 1 ; i++ )
			list.add( 0 ) ;
		
		int currentVertexOffset = list.size() ;
		
		for( int i = 0 ; i < size ; i++ )
		{
			list.set( vericesOffsetsStart + i,  currentVertexOffset ) ;
			
			MarkedVertex currentVertex = vertices.get(i);
			
//			list.add( currentVertex.parent ) ;
//			vericesOffsetsStart++ ;
			
			ArrayList<Integer> currentVertexChildren = currentVertex.getChildren() ;			
			for( int n : currentVertexChildren ){
				list.add(n) ;
				vericesOffsetsStart++ ;
			}
		}
		list.set( vericesOffsetsStart + size,  currentVertexOffset ) ;
		
		int size2 = list.size();
		int[] result = new int[ size2 ] ;
		for( int i = 0 ; i < size2 ; i++ )
			result[i] = list.get(i) ;
		
		return result ;
	}
	
	private void takeSpecificationArray( int[] inputArray )
	{
		if( inputArray == null || inputArray.length == 0 )
			return ;
		
		int size = inputArray[0] ;
		int vericesOffsetsStart = 1 ;
		if( vertices == null )
			vertices = new ArrayList<MarkedTree.MarkedVertex>( size ) ;
		
		vertices.clear() ;
		
		for( int i = 0 ; i < size ; i++ ){
			MarkedVertex newVert = new MarkedVertex();
			newVert.setIndex(i) ;
			vertices.add( newVert ) ;
		}
		
		for( int i = 0 ; i < size ; i ++ )
		{
			MarkedVertex currentVertex = vertices.get(i) ;
			int vertexDataStart = inputArray[vericesOffsetsStart + i     ] ;
			int vertexDataEnd   = inputArray[vericesOffsetsStart + i + 1 ] ;
			
			//currentVertex.setParent( inputArray[vertexDataStart] ) ;			
			for( int j = vertexDataStart ; j < vertexDataEnd ; j++ )
				currentVertex.addChild( inputArray[j] ) ;			
		}
	}

}
